#include "app/app_device.h"
#include <stdlib.h>
#include <string.h>
#include "app/app_buffer.h"
#include "app/app_message.h"
#include "app/app_task.h"
#include "thirdparty/log.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>

#define BUFFER_LEN 16384

static void* app_device_backgroundDefaultTask(void *argv)
{
    Device *device = argv;
    unsigned char buf[1024];
    while (1) {
        // 读取设备数据
        int buf_len = read(device->fd, buf, 1024);
        if(buf_len < 0)
        {
            continue;
        }
        // 写入缓存
        if(device->vptr->post_read)
        {
            device->vptr->post_read(device, buf, &buf_len);
        }

        if(buf_len > 0)
        {
            app_buffer_write(device->recv_buffer, buf, buf_len);
        }

        // 注册一个发送任务， 让线程池处理
        app_task_register(device->vptr->recv_task, device);   
    }
    return NULL;
}

static void app_device_defaultRecvTask(void *argv)
{
    unsigned char buf[1024];
    Device *device = argv;
    // 读取缓冲区的数据
    app_buffer_read(device->recv_buffer, buf, 3);
    app_buffer_read(device->recv_buffer, buf+3 , buf[1] + buf[2]);
    int buf_len = 3 + buf[1] + buf[2];
    // 调用发送回调函数
    while (device->vptr->recv_callback(buf, buf_len) < 0) {
        usleep(100000);
    }
    
}

static void app_device_defaultSendTask(void *argv)
{
    Device *device = argv;
    // 从缓冲区中读取二进制数据
    unsigned char buf[1024];
    int buf_len = 0;
    app_buffer_read(device->send_buffer, buf, 3);
    app_buffer_read(device->send_buffer, buf + 3, buf[1] + buf[2]);
    buf_len = 3 + buf[1] + buf[2];

    // 将消息写入到设备文件描述符
    // 写前处理
    if(device->vptr->pre_write)
    {
        device->vptr->pre_write(device, buf, &buf_len);
    }
    
    // 约定， 如果写先处理的数据长度为0. 表示不需要写入
    if(buf_len > 0)
    {
        write(device->fd, buf, buf_len);
    }

}



int app_device_init(Device *device, char *filename)
{
    device->filename = malloc(strlen(filename)+1);
    if(!device->filename)
    {
        log_warn("Not enough memory for device %s", filename);
        goto DEVICE_EXIT;
    }

    device->vptr = malloc(sizeof(struct VTable));
    if(!device->vptr)
    {
        log_warn("Not enough memory for device %s", filename);
        goto DEVICE_FILENAME_EXIT;
    }

    device->recv_buffer = malloc(sizeof(Buffer));
    if(!device->recv_buffer)
    {
        log_warn("Not enough memory for device %s", filename);
        goto DEVICE_VPTR_EXIT;
    }

    device->send_buffer = malloc(sizeof(Buffer));
    if(!device->send_buffer)
    {
        log_warn("Not enough memory for device %s", filename);
        goto DEVICE_RECV_BUFFER_EXIT;
        
    }

    strcpy(device->filename, filename);
    device->fd = open(device->filename, O_RDWR | O_NOCTTY);
    if(device->fd < 0)
    {
        log_warn("Device open failed");
        goto DEVICE_SEND_BUFFER_EXIT;
    }

    device->connection_type = CONNECTION_TYPE_NONE;

    
    if(app_buffer_init(device->send_buffer, BUFFER_LEN) < 0)
    {
        goto DEVICE_OPEN_FAIL;
    }
    if(app_buffer_init(device->recv_buffer, BUFFER_LEN) < 0)
    {
        goto DEVICE_SEND_INIT_FAIL;
    }

    device->is_running = 0;
    // TODO 虚表也需要初始化
    device->vptr->send_task = app_device_defaultSendTask;
    device->vptr->pre_write = NULL;
    device->vptr->background_task = app_device_backgroundDefaultTask;
    device->vptr->recv_task = app_device_defaultRecvTask;
    device->vptr->post_read = NULL;
    device->vptr->recv_callback = NULL;
    return 0;
// DEVICE_RECV_INIT_FAIL:
//     app_buffer_close(device->recv_buffer);
DEVICE_SEND_INIT_FAIL:
    app_buffer_close(device->send_buffer);    
DEVICE_OPEN_FAIL:
    close(device->fd);
DEVICE_SEND_BUFFER_EXIT:
    free(device->send_buffer);

DEVICE_RECV_BUFFER_EXIT:
    free(device->recv_buffer);

DEVICE_VPTR_EXIT:
    free(device->vptr);

DEVICE_FILENAME_EXIT:
    free(device->filename);

DEVICE_EXIT:
    return -1;
}


// 启动设备后台线程
int app_device_start(Device *device)
{   
    if(device->is_running)
    {
        return -1;
    }
    if(pthread_create(&device->background_thread, NULL, device->vptr->background_task, device) < 0)
    {
        log_error("Failed to create background thread");
        return -1;
    }
    device->is_running = 1;
    return 0;
}

// 停止设备后台线程
void app_device_stop(Device *device)
{
    if(device->is_running)
    {
        pthread_cancel(device->background_thread);
        pthread_join(device->background_thread, NULL);
    }
    device->is_running = 0;
}

int app_device_write(Device *device, void *ptr, int len)
{   
    // 写入缓存
    if(app_buffer_write(device->send_buffer, ptr,len) < 0)
    {
        return -1;
    }
    // 注册一个Task, 将缓存区的数据写入设备
    if(app_task_register(device->vptr->send_task, device) < 0)
    {
        return -1;
    }


    return 0;
}

// 这里需要一个注册回调函数方法
void app_device_registerRecvCallback(Device *device, int (*recv_callback)(void *,int))
{
    device->vptr->recv_callback = recv_callback;
}


void app_device_close(Device *device)
{
    app_buffer_close(device->recv_buffer);
    app_buffer_close(device->send_buffer);    
    close(device->fd);
    free(device->send_buffer);
    free(device->recv_buffer);
    free(device->vptr);
    free(device->filename);
}